package com.ccf.business.knowledge.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ccf.business.knowledge.model.vo.LabelTaskVO;
import com.google.common.collect.Lists;
import com.ccf.business.knowledge.mapper.LabelTaskTypeMapper;
import com.ccf.business.knowledge.model.LabelTask;
import com.ccf.business.knowledge.model.LabelTaskType;
import com.ccf.business.knowledge.model.vo.RelationTypeVO;
import com.ccf.business.knowledge.service.ILabelTaskTypeService;
import com.common.link.cache.AtlasCache;
import com.common.link.cache.AtlasCacheService;
import com.common.link.model.EntityVO;
import com.common.link.model.RelationAndEntityVO;
import com.common.model.pojo.Query;
import com.common.model.result.CodeEnum;
import com.common.model.result.PageResult;
import com.service.mybatis.service.impl.SuperServiceImpl;
import com.service.mybatis.util.Condition;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 任务实体关系
 *
 * @author ccf
 * @date 2022-02-15 16:56:10
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LabelTaskTypeServiceImpl extends SuperServiceImpl<LabelTaskTypeMapper, LabelTaskType> implements ILabelTaskTypeService {

    private final AtlasCacheService atlasCacheService;

    /**
    * 列表
    * @param query
    * @return
    */
    @Override
    public PageResult<LabelTaskType> findList(Query query){
        Page<LabelTaskType> page = page(Condition.getPage(query), Condition.getQueryWrapper(query));
        return PageResult.<LabelTaskType>builder().datas(page.getRecords()).code(CodeEnum.SUCCESS.getCode()).count(page.getTotal()).build();
    }

    @Override
    public List<EntityVO> entityList(String taskId) {
        List<LabelTaskType> list = list(Wrappers.<LabelTaskType>query()
                .lambda().eq(LabelTaskType::getTaskId, taskId));
        List<EntityVO> entityVOS = Lists.newArrayList();
        for (LabelTaskType type : list) {
            String endityId = type.getEndityId();
            if (StrUtil.isNotBlank(endityId)){
                EntityVO entityById = atlasCacheService.getEntityById(endityId);
                entityVOS.add(entityById);
            }
            String entityId = type.getEntityId();
            if (StrUtil.isNotBlank(entityId)){
                EntityVO entityById = atlasCacheService.getEntityById(entityId);
                entityVOS.add(entityById);
            }
        }
        entityVOS = entityVOS.stream().distinct().collect(Collectors.toList());
        return entityVOS;
    }

    @Override
    public List<RelationAndEntityVO> relationList(String taskId, String beginId, String endId) {
        List<LabelTaskType> list = list(Wrappers.<LabelTaskType>query()
                .lambda().eq(LabelTaskType::getTaskId, taskId));
        list = list.stream()
                .filter(e -> StrUtil.isNotBlank(e.getRelationId())
                        && StrUtil.isNotBlank(e.getEndityId())
                        && StrUtil.isNotBlank(e.getEntityId()))
                .collect(Collectors.toList());
        List<RelationAndEntityVO> entityVOS = Lists.newArrayList();
        for (LabelTaskType type : list) {
            String entityId = type.getEntityId();
            Optional<EntityVO> beginVo = Optional.ofNullable(atlasCacheService.getEntityById(entityId));
            String endityId = type.getEndityId();
            Optional<EntityVO> endVo = Optional.ofNullable(atlasCacheService.getEntityById(endityId));
            RelationAndEntityVO relationAndEntityVO = new RelationAndEntityVO();
            if (beginId != null && endId != null && beginId.equalsIgnoreCase(entityId)
                    && endId.equalsIgnoreCase(endityId)){
                relationAndEntityVO.setMatches(true);
            } else {
                relationAndEntityVO.setMatches(false);
            }
            relationAndEntityVO.setId(type.getRelationId());
            relationAndEntityVO.setName(AtlasCache.get(type.getRelationId()));
            relationAndEntityVO
                    .setSourceId(entityId);
            relationAndEntityVO.setSourceName(beginVo.map(EntityVO::getName).orElse(null));
            relationAndEntityVO.setTargetId(endityId);
            relationAndEntityVO.setTargetName(endVo.map(EntityVO::getName).orElse(null));
            entityVOS.add(relationAndEntityVO);
        }
        entityVOS.sort((o1,o2)-> {
            if (o1.getMatches() ^ o2.getMatches()) {
                return o1.getMatches() ? -1 : 1;
            } else {
                return 0;
            }
        });
        return entityVOS;
    }



    /**
     * 保存类型
     * @param labelTask
     */
    @Override
    public void saveTypes(LabelTaskVO labelTask, boolean isUpdate) {
        String id = labelTask.getId();
        //类型
        List<LabelTaskType> types = Lists.newArrayList();
        //是否是实体标注
        if (LabelTask.ENTITY.equalsIgnoreCase(labelTask.getLabelType())){
            String[] entities = labelTask.getEntityList();

            for (String entityType : entities) {
                EntityVO entityVO = atlasCacheService.getEntityById(entityType);
                LabelTaskType labelTaskType = LabelTaskType.builder()
                        .taskId(id)
                        .entityId(entityType)
                        .entityName(Optional.ofNullable(entityVO).map(EntityVO::getName).orElse(null))
                        .build();
                types.add(labelTaskType);
            }
        } else if (LabelTask.RELATION.equalsIgnoreCase(labelTask.getLabelType())){
            RelationTypeVO[] relations = labelTask.getRelationList();
            for (RelationTypeVO relation : relations) {
                EntityVO sourceEntity = atlasCacheService.getEntityById(relation.getSourceId());
                EntityVO targetEntity = atlasCacheService.getEntityById(relation.getTargetId());
                LabelTaskType labelTaskType = LabelTaskType.builder()
                        .taskId(id)
                        .entityId(relation.getSourceId())
                        .entityName(Optional.ofNullable(sourceEntity).map(EntityVO::getName).orElse(null))
                        .relationId(relation.getRelationId())
                        .relationName(AtlasCache.get(relation.getRelationId()))
                        .endityId(relation.getTargetId())
                        .endityName(Optional.ofNullable(targetEntity).map(EntityVO::getName).orElse(null))
                        .build();
                types.add(labelTaskType);
            }
        }
        if (types.size() > 0){
            if (isUpdate){
                List<LabelTaskType> oldDatas = list(Wrappers.<LabelTaskType>query()
                        .lambda().eq(LabelTaskType::getTaskId, id));
                if (CollUtil.isNotEmpty(oldDatas)){
                    removeByIds(oldDatas.stream().map(e->e.getId()).collect(Collectors.toList()));
                }
            }
            saveBatch(types);
        }
    }

}
